import InputUtil from "@/InputUtil";
import SelectUtil from "@/SelectUtil";
import SyncUtil from "@/SyncUtil";
import { Frame } from "@/frame";
import { Trigger } from "@/trigger";

interface BackPackItem {
  id: string;
  count: number;
  art: string;
  canStatck: boolean;
}

enum BackPackCommand {
  AddItem = "AddItem",
  RemoveItem = "RemoveItem",
  Clear = "Clear",
  Open = "Open",
}

interface GirdMapData {
  bg: Frame;
  text: Frame;
  but: Frame;
  index: number;
  x: number;
  y: number;
}

interface BackPackDB {
  [key: number]: BackPackItem[];
}
export default class 背包系统 {
  /**  背包数据 */
  static db: BackPackDB = {};
  /** 拾取状态 */
  static pickItemStatus: boolean[] = [];
  /** 移动状态 */
  static moveItemStatus: boolean[] = [];
  /** 背包ui根节点 */
  static RootFrame: Frame;
  /** 操作的物品ui对象 */
  static movingGrid: GirdMapData;
  /** 随着鼠标移动的ui */
  static Cursor: Frame;
  /** 以按钮为索引，存储相关ui */
  static girdMap = new Map<number, GirdMapData>();
  /** 使用索引对每个背包按钮进行存储 */
  static gridsData: number[] = [];
  /* 提示 */
  static tipFrame: Frame;
  constructor() {
    // 初始化存储
    for (let i = 0; i < 12; i++) {
      背包系统.db[i] = [];
      背包系统.pickItemStatus[i] = true;
    }

    // 事件
    SyncUtil.onSyncObjData(BackPackCommand.Open, 背包系统.OpenBackPack); // 打开背包
    SyncUtil.onSyncObjData(BackPackCommand.RemoveItem, 背包系统.DropItemHandle); // 丢弃物品
    SyncUtil.onSyncObjData(BackPackCommand.AddItem, 背包系统.AddItemHandle); // 生成物品到物品栏
    DzTriggerRegisterMouseEventByCode(
      CreateTrigger(),
      2,
      0,
      false,
      背包系统.rightClickEventHandle
    ); //鼠标右键释放
    DzTriggerRegisterMouseEventByCode(
      CreateTrigger(),
      1,
      1,
      false,
      背包系统.leftClickEventHandle
    ); //鼠标左键点击

    InputUtil.onMouseMoveEvent(背包系统.mouseMoveEventHandle);

    // 拾取物品事件
    let trigger = new Trigger();
    trigger.registerAnyUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM);
    trigger.addAction(背包系统.pickupItemAction);

    // 绘制ui
    this.drawUI();
  }
  static AddItemHandle(p: player, data: BackPackItem) {
    let id = GetPlayerId(p);
    背包系统.pickItemStatus[id] = false;
    let u = SelectUtil.getAnHero(id);
    let item = CreateItem(data.id, GetUnitX(u), GetUnitY(u));
    SetItemCharges(item, data.count);
    UnitAddItem(u, item);
    // BJDebugMsg("添加物品:" + GetItemName(item));
  }
  static leftClickEventHandle(this: void) {
    let n = DzGetMouseFocus();
    let p = DzGetTriggerKeyPlayer();
    let id = GetPlayerId(p);
    // 正在移动则不处理
    if (背包系统.moveItemStatus[id]) {
      return;
    }
    if (n == 0) return;
    let g = 背包系统.girdMap.get(n);
    if (g == null) return;
    let data = 背包系统.db[id][g.index];
    if (data == null) return;
    // 背包系统.pickItemStatus[id] = false;
    // // 清空数据
    背包系统.db[id][g.index] = null;
    // let u = SelectUtil.getAnHero(GetPlayerId(p));
    SyncUtil.syncObjData(BackPackCommand.AddItem, data);
    // 更新ui
    if (p == GetLocalPlayer()) {
      g.bg.setTexture("assets\\backpack\\grid.blp");
      g.text.setText("");
    }
  }
  // 丢下物品
  static DropItemHandle(
    p: player,
    { id, count, x, y }: BackPackItem & { x: number; y: number }
  ) {
    let item = CreateItem(id, x, y);
    SetItemCharges(item, count);
    BJDebugMsg("DropItemHandle" + GetItemName(item));
  }
  // 鼠标移动处理
  static mouseMoveEventHandle(this: void) {
    let p = DzGetTriggerKeyPlayer();
    if (p == GetLocalPlayer()) {
      let id = GetPlayerId(p);
      if (背包系统.Cursor.visible && 背包系统.moveItemStatus[id]) {
        背包系统.Cursor.setAbsPoint(
          FRAMEPOINT_BOTTOMLEFT,
          InputUtil.getMouseSceneX() + 0.005,
          InputUtil.getMouseSceneY() + 0.005
        );
      }
    }
  }
  // 打开背包
  static OpenBackPack(p: player, data) {}
  // 绘制ui
  drawUI() {
    // 绘制ui
    let f = Frame.createFrame();
    let bg = Frame.createBackDrop(f.current);
    bg.setTexture("assets\\backpack\\bag.blp");
    bg.setSize(0.04, 0.04).setAbsPoint(FRAMEPOINT_BOTTOMLEFT, 0.04, 0.165);
    let bagBut = Frame.createGLUETEXTBUTTON(bg.current);
    bagBut.setSize(0.04, 0.04).setPoint2Center(bg.current);
    bagBut.addOnClick(背包系统.bagButClickHandle);

    // 背包根ui
    背包系统.RootFrame = Frame.createFrame();
    背包系统.RootFrame.setSize(0.26, 0.24)
      .setAbsPoint(FRAMEPOINT_BOTTOMLEFT, 0.5, 0.2)
      .setVisible(false);
    背包系统.RootFrame.addBackgroundImage("assets\\backpack\\black.blp");
    let tip = Frame.createTEXT(背包系统.RootFrame.current)
      .setSize(0.26, 0.012)
      .setText("右键移动物品，左键放入物品栏")
      .setFont(0.01, "assets\\fonts\\fonts.ttf");
    tip.setPoint(
      FRAMEPOINT_TOP,
      背包系统.RootFrame.current,
      FRAMEPOINT_TOP,
      0,
      -0.005
    );
    tip.setTextAlignment(TEXTALIGN_CENTER);

    // 提示ui
    背包系统.tipFrame = Frame.createTEXT()
      .setFont(0.012, "assets\\fonts\\fonts.ttf")
      .setPoint(
        FRAMEPOINT_TOPRIGHT,
        背包系统.RootFrame.current,
        FRAMEPOINT_TOPLEFT,
        -0.01,
        -0.05
      )
      .setSize(0.2, 0);
    let fbg = new Frame("BACKDROP", null, null, "_sl_border_backdrop", 0);
    fbg
      .setParent(背包系统.tipFrame.current)
      .setPoints(背包系统.tipFrame.current, 0.008, 0.008);
    背包系统.tipFrame.setVisible(false);

    // 绘制背包格子
    for (let i = 0; i < 30; i++) {
      let g = Frame.createFrame();
      let x = 0.01 + (i % 6) * 0.04;
      let y = -0.03 + Math.floor(i / 6) * -0.04;
      g.setSize(0.04, 0.04)
        .setParent(背包系统.RootFrame.current)
        .setPoint(
          FRAMEPOINT_TOPLEFT,
          背包系统.RootFrame.current,
          FRAMEPOINT_TOPLEFT,
          x,
          y
        );
      let img = g.addBackgroundImage("assets\\backpack\\grid.blp");
      let text = Frame.createTEXT(g.current).setSize(0.038, 0.012);
      text
        .setText("")
        .setFont(0.01, "assets\\fonts\\fonts.ttf")
        .setPoint(FRAMEPOINT_BOTTOM, g.current, FRAMEPOINT_BOTTOM, 0, 0.001)
        .setTextAlignment(TEXTALIGN_RIGHT);
      let but = Frame.createBUTTON(g.current)
        .setSize(0.04, 0.04)
        .setPoint(FRAMEPOINT_CENTER, g.current, FRAMEPOINT_CENTER);
      // 以按钮为索引，存储相关ui
      背包系统.girdMap.set(but.current, {
        bg: img,
        text: text,
        but: but,
        index: i,
        x,
        y,
      });
      // 以顺序为索引，存储按钮
      背包系统.gridsData[i] = but.current;

      but.setOnMouseEnter(背包系统.showBuffTip);
      but.setOnMouseLeave(背包系统.hideBuffTip);
    }

    背包系统.Cursor = Frame.createBackDrop();
    背包系统.Cursor.setSize(0.04, 0.04).setScale(0.8).setVisible(false);
  }
  static showBuffTip(this: void) {
    let handle = DzGetTriggerUIEventFrame();
    let p = DzGetTriggerUIEventPlayer();
    if (p == GetLocalPlayer()) {
      let g = 背包系统.girdMap.get(handle);
      let d = 背包系统.db[GetPlayerId(p)][g.index];
      if (d == null) return;
      背包系统.tipFrame.setVisible(true);
      let text = `${EXGetItemDataString(d.id, 4)}|n|n${EXGetItemDataString(
        d.id,
        3
      )}`;
      背包系统.tipFrame.setText(text);
    }
  }
  static hideBuffTip(this: void) {
    背包系统.tipFrame.setVisible(false);
  }
  // 背包按钮点击
  static bagButClickHandle(this: void) {
    let p = DzGetTriggerUIEventPlayer();
    let id = GetPlayerId(p);
    背包系统.RootFrame.visible = !背包系统.RootFrame.visible;
    SyncUtil.syncObjData(BackPackCommand.Open, { id });
  }
  // 鼠标右键释放处理
  static rightClickEventHandle(this: void) {
    let n = DzGetMouseFocus();
    let p = DzGetTriggerKeyPlayer();
    let id = GetPlayerId(p);
    let index = 背包系统.isInGrid(n);
    if (index != null) {
      // 右键在背包格子上
      let grid = 背包系统.girdMap.get(n);
      // 如果背包格子有物品
      let tarItem = 背包系统.gridHasItem(id, grid.but.current);
      if (tarItem != null) {
        // 并且不是移动状态
        if (!背包系统.moveItemStatus[id]) {
          // 标记为移动状态
          背包系统.moveItemStatus[id] = true;
          背包系统.movingGrid = grid;
          // 更新ui
          if (p == GetLocalPlayer()) {
            // 显示鼠标移动图标
            let x = InputUtil.getMouseSceneX();
            let y = InputUtil.getMouseSceneY();
            背包系统.Cursor.setVisible(true)
              .setTexture(grid.bg.getTexture() as string)
              .setAbsPoint(FRAMEPOINT_BOTTOMLEFT, x + 0.005, y + 0.005);

            // 隐藏 原物品ui
            grid.bg.setTexture("assets\\backpack\\grid.blp");
            grid.text.setText("");
          }
        } else {
          // 交换物品
          // 先保留一份目标格子的数据;
          let targetItemData = 背包系统.db[id][grid.index]; // 目标格子物品数据
          // 交换数据
          // 把正在移动的，就是原来格子的数据赋值给新的目标格子
          背包系统.db[id][grid.index] =
            背包系统.db[id][背包系统.movingGrid.index];

          // 把目标格子的数据赋值给原来被移动的格子的数据
          背包系统.db[id][背包系统.movingGrid.index] = targetItemData;

          if (p == GetLocalPlayer()) {
            // 更新ui
            grid.bg.setTexture(背包系统.db[id][grid.index]?.art); // 目标格子
            if (背包系统.db[id][grid.index].canStatck) {
              // @ts-ignore
              grid.text.setText(背包系统.db[id][grid.index].count);
            } else {
              grid.text.setText("");
            }
            背包系统.girdMap
              .get(背包系统.movingGrid.but.current)
              .bg.setTexture(targetItemData.art); // 原来格子
            if (targetItemData.canStatck) {
              // @ts-ignore
              背包系统.girdMap
                .get(背包系统.movingGrid.but.current)
                .text.setText(`${targetItemData.count}`);
            } else {
              背包系统.girdMap
                .get(背包系统.movingGrid.but.current)
                .text.setText("");
            }
            //
            背包系统.Cursor.setVisible(false);
          }
          // 标记移动完成
          背包系统.movingGrid = null;
          背包系统.moveItemStatus[id] = false;
        }
      } else {
        // 背包格子没有物品
        // 如果是移动状态
        if (背包系统.moveItemStatus[id]) {
          // 交换物品
          // 直接把目标格子的数据修改
          背包系统.db[id][grid.index] =
            背包系统.db[id][背包系统.movingGrid.index];
          // 把原来的数据置空
          背包系统.db[id][背包系统.movingGrid.index] = null;

          if (p == GetLocalPlayer()) {
            // 更新ui
            grid.bg.setTexture(背包系统.db[id][grid.index].art); // 目标格子
            if (背包系统.db[id][grid.index].canStatck) {
              // @ts-ignore
              grid.text.setText(背包系统.db[id][grid.index].count);
            } else {
              grid.text.setText("");
            }
            //
            背包系统.Cursor.setVisible(false);
          }
          // 标记移动完成
          背包系统.movingGrid = null;
          背包系统.moveItemStatus[id] = false;
        }
      }
    } else if (n == 0) {
      // 没有在任何ui上
      // 并且在移动状态
      if (背包系统.moveItemStatus[id]) {
        // 丢下物品
        let data = 背包系统.db[id][背包系统.movingGrid.index];
        背包系统.db[id][背包系统.movingGrid.index] = null;
        // 更新ui
        if (p == GetLocalPlayer()) {
          背包系统.Cursor.setVisible(false);
        }
        let x = DzGetMouseTerrainX();
        let y = DzGetMouseTerrainY();

        // 同步创建物品
        SyncUtil.syncObjData(BackPackCommand.RemoveItem, { ...data, x, y });
        // 标记移动完成
        背包系统.movingGrid = null;
        背包系统.moveItemStatus[id] = false;
      }
    } else {
      // 如果正在移动状态
      if (背包系统.moveItemStatus[id]) {
        let old = 背包系统.movingGrid;
        let d = 背包系统.db[id][old.index];
        // 还原ui
        if (p == GetLocalPlayer()) {
          背包系统.Cursor.setVisible(false);
          背包系统.girdMap.get(old.but.current).bg.setTexture(d.art);
          if (d.canStatck) {
            // @ts-ignore
            背包系统.girdMap.get(old.but.current).text.setText(d.count);
          } else {
            背包系统.girdMap.get(old.but.current).text.setText("");
          }
        }
        // 还原状态
        背包系统.movingGrid = null;
        背包系统.moveItemStatus[id] = false;
      }
    }
  }
  static gridHasItem(id: number, g: number) {
    return 背包系统.db[id][背包系统.girdMap.get(g).index];
  }
  // 是否触发的背包格子
  static isInGrid(handle: number) {
    for (let i = 0; i < 30; i++) {
      if (背包系统.gridsData[i] === handle) {
        return i;
      }
    }
    return null;
  }
  // 拾取物品处理
  static pickupItemAction(this: void) {
    let p = GetTriggerPlayer();
    let u = GetTriggerUnit();
    let item = GetManipulatedItem();
    let id = GetPlayerId(p);

    // 如果是自动使用的物品
    if (GetItemType(item) == ITEM_TYPE_POWERUP) return;
    if (IsItemPowerup(item)) return;
    if (背包系统.pickItemStatus[id]) {
      let t = GetItemType(item);
      let canStatck = t === ITEM_TYPE_CHARGED;
      let itemTypeId = id2string(GetItemTypeId(item));
      // 优先找可以叠加的格子
      if (canStatck) {
        let index = 背包系统.findAnSameAndCanStatckGrid(id, itemTypeId);
        if (index != null) {
          // 有相同并可以叠加的格子
          // 叠加物品
          背包系统.db[id][index].count += GetItemCharges(item);
          // 只有更新ui操作是在本地玩家环境下操作
          if (p == GetLocalPlayer()) {
            // 更新ui
            let but = 背包系统.gridsData[index];
            let fs = 背包系统.girdMap.get(but);
            // @ts-ignore
            fs.text.setText(背包系统.db[id][index].count);
          }
          // 从单位身上移除物品
          UnitRemoveItemSwapped(item, u);
          RemoveItem(item);
        } else {
          // 没有可以叠加的格子
          背包系统.addItemToBackPack(p, item, u, itemTypeId, canStatck);
        }
      } else {
        背包系统.addItemToBackPack(p, item, u, itemTypeId, canStatck);
      }
    } else {
      背包系统.pickItemStatus[id] = true;
    }
  }
  // 找一个空格子
  static findAnEmptyGrid(id: number) {
    let db = 背包系统.db[id];
    if (db) {
      for (let i = 0; i < 30; i++) {
        if (db[i] == null) {
          return i;
        }
      }
    }
    return null;
  }
  // 找相同并且可以叠加的格子
  static findAnSameAndCanStatckGrid(id: number, itemTypeId: string) {
    let db = 背包系统.db[id];
    if (db) {
      for (let i = 0; i < 30; i++) {
        // 找相同并且可以叠加的格子
        if (db[i] && db[i].id === itemTypeId && db[i].canStatck) {
          return i;
        }
      }
    }
    return null;
  }
  // 添加物品进背包
  static addItemToBackPack(
    p: player,
    item: item,
    u: unit,
    itemTypeId: string,
    canStatck: boolean
  ) {
    let id = GetPlayerId(p);
    // 找一个格格子
    let index = 背包系统.findAnEmptyGrid(id);
    if (index == null) {
      // 没有格子了。
      print("没有格子了!");
      // 丢下物品
      // UnitRemoveItemSwapped(item, u);
      return;
    }
    // 找到空格子
    let db = 背包系统.db[id];
    // 存储
    db[index] = {
      id: itemTypeId,
      art: EXGetItemDataString(itemTypeId, 1),
      count: GetItemCharges(item),
      canStatck,
    };
    // 从单位身上移除物品
    UnitRemoveItemSwapped(item, u);
    RemoveItem(item);
    if (p == GetLocalPlayer()) {
      // 更新ui
      let d = 背包系统.gridsData[index];
      let data = 背包系统.girdMap.get(d);
      if (canStatck) {
        data.text.setText(db[index].count + "");
      }
      data.bg.setTexture(db[index].art);
    }
  }
}
